package cn.tqfeiyang.smartadmin.system.service;

import cn.hutool.cache.Cache;
import cn.tqfeiyang.smartadmin.commons.exception.InternalException;
import cn.tqfeiyang.smartadmin.commons.toolbox.CacheUtils;
import cn.tqfeiyang.smartadmin.commons.toolbox.StringUtils;
import cn.tqfeiyang.smartadmin.system.entity.ConfigEntity;
import cn.tqfeiyang.smartadmin.system.mapper.ConfigMapper;
import cn.tqfeiyang.smartadmin.system.request.ConfigCreateDTO;
import cn.tqfeiyang.smartadmin.system.request.ConfigUpdateDTO;
import cn.tqfeiyang.smartadmin.system.request.ConfigQueryDTO;
import cn.tqfeiyang.smartadmin.system.response.ConfigQueryVO;
import cn.tqfeiyang.smartadmin.system.response.ConfigDetailVO;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.github.pagehelper.PageHelper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import cn.tqfeiyang.smartadmin.commons.exception.BusinessException;
import cn.tqfeiyang.smartadmin.commons.pagination.PageData;
import cn.tqfeiyang.smartadmin.commons.toolbox.BeanUtils;
import cn.tqfeiyang.smartadmin.commons.toolbox.ValidationUtils;

import java.util.List;
import java.util.Optional;

/**
 * 配置服务
 *
 * @author tqfeiyang
 * @since 2024-08-23
 */
@Slf4j
@Service
public class ConfigService {

    /**
     * 配置映射接口
     */
    @Resource
    private ConfigMapper configMapper;

    /**
     * 查询配置
     *
     * @param dto 请求数据
     * @return 配置列表
     */
    public PageData<ConfigQueryVO> queryConfigs(ConfigQueryDTO dto) {
        ValidationUtils.validateProperties(dto);
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<ConfigEntity> list = configMapper.selectList(dto.getWrapper());
        return PageData.create(list, ConfigQueryVO.class);
    }

    /**
     * 获取配置
     *
     * @param configId 配置id
     * @return 配置信息
     */
    public ConfigDetailVO readConfig(Long configId) {
        ConfigEntity configEntity = checkConfigExists(configId);
        return BeanUtils.map(configEntity, ConfigDetailVO.class);
    }

    /**
     * 添加配置
     *
     * @param dto 请求数据
     * @return 配置id
     */
    @Transactional(rollbackFor = Exception.class)
    public Long createConfig(ConfigCreateDTO dto) {
        ValidationUtils.validateProperties(dto);
        ConfigEntity configEntity = BeanUtils.copy(dto, ConfigEntity.class);
        configMapper.insert(configEntity);
        return configEntity.getConfigId();
    }

    /**
     * 修改配置
     *
     * @param configId 配置id
     * @param dto 请求数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateConfig(Long configId, ConfigUpdateDTO dto) {
        checkConfigExists(configId);
        ValidationUtils.validateProperties(dto);
        ConfigEntity configEntity = BeanUtils.copy(dto, ConfigEntity.class);
        configEntity.setConfigId(configId);
        configMapper.updateById(configEntity);
    }

    /**
     * 删除配置
     *
     * @param configId 配置id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteConfig(Long configId) {
        checkConfigExists(configId);
        configMapper.deleteById(configId);
    }

    /**
     * 检查配置实体是否存在
     *
     * @param configId 配置id
     * @return 配置实体
     */
    protected ConfigEntity checkConfigExists(Long configId) {
        Assert.notNull(configId, "configId不能为空");
        ConfigEntity configEntity = configMapper.selectById(configId);
        if (ObjectUtils.isEmpty(configEntity)) {
            throw new BusinessException("配置不存在");
        }
        return configEntity;
    }

    //===================================================================================

    private List<ConfigEntity> configCache = null;

    public void loadAllConfigs() {
        log.debug("加载配置到缓存");
        configCache = configMapper.selectList(null);
    }

    public void cleanConfigCache() {
        log.debug("清理缓存的配置");
        configCache = null;
    }

    public String getConfigValue(String key) {
        ConfigEntity configEntity = findConfigEntity(key);
        return configEntity.getValue();
    }

    public void setConfigValue(String key, String value) {
        ConfigEntity configEntity = findConfigEntity(key);
        configEntity.setValue(value);

        // 只需要更新 id 和 value 这两个字段
        ConfigEntity updatedEntity = new ConfigEntity();
        updatedEntity.setConfigId(configEntity.getConfigId());
        updatedEntity.setValue(configEntity.getValue());
        configMapper.updateById(updatedEntity);
    }

    private ConfigEntity findConfigEntity(String key) {
        if (configCache == null) {
            loadAllConfigs();
        }

        Optional<ConfigEntity> configOptional = configCache.stream()
                .filter(entity -> StringUtils.equalsIgnoreCase(key, entity.getCode()))
                .findFirst();
        if (configOptional.isEmpty()) {
            throw new InternalException(String.format("配置key不存在 (%s)", key));
        }
        return configOptional.get();
    }
}
